home *** CD-ROM | disk | FTP | other *** search
- # Source Generated with Decompyle++
- # File: in.pyc (Python 2.6)
-
- '''
- MAIN CLASS FOR TLS LITE (START HERE!).
- '''
- from __future__ import generators
- import socket
- from utils.compat import formatExceptionTrace
- from TLSRecordLayer import TLSRecordLayer
- from Session import Session
- from constants import *
- from utils.cryptomath import getRandomBytes
- from errors import *
- from messages import *
- from mathtls import *
- from HandshakeSettings import HandshakeSettings
-
- class TLSConnection(TLSRecordLayer):
- '''
- This class wraps a socket and provides TLS handshaking and data
- transfer.
-
- To use this class, create a new instance, passing a connected
- socket into the constructor. Then call some handshake function.
- If the handshake completes without raising an exception, then a TLS
- connection has been negotiated. You can transfer data over this
- connection as if it were a socket.
-
- This class provides both synchronous and asynchronous versions of
- its key functions. The synchronous versions should be used when
- writing single-or multi-threaded code using blocking sockets. The
- asynchronous versions should be used when performing asynchronous,
- event-based I/O with non-blocking sockets.
-
- Asynchronous I/O is a complicated subject; typically, you should
- not use the asynchronous functions directly, but should use some
- framework like asyncore or Twisted which TLS Lite integrates with
- (see
- L{tlslite.integration.TLSAsyncDispatcherMixIn.TLSAsyncDispatcherMixIn} or
- L{tlslite.integration.TLSTwistedProtocolWrapper.TLSTwistedProtocolWrapper}).
- '''
-
- def __init__(self, sock):
- '''Create a new TLSConnection instance.
-
- @param sock: The socket data will be transmitted on. The
- socket should already be connected. It may be in blocking or
- non-blocking mode.
-
- @type sock: L{socket.socket}
- '''
- TLSRecordLayer.__init__(self, sock)
-
-
- def handshakeClientSRP(self, username, password, session = None, settings = None, checker = None, async = False):
- """Perform an SRP handshake in the role of client.
-
- This function performs a TLS/SRP handshake. SRP mutually
- authenticates both parties to each other using only a
- username and password. This function may also perform a
- combined SRP and server-certificate handshake, if the server
- chooses to authenticate itself with a certificate chain in
- addition to doing SRP.
-
- TLS/SRP is non-standard. Most TLS implementations don't
- support it. See
- U{http://www.ietf.org/html.charters/tls-charter.html} or
- U{http://trevp.net/tlssrp/} for the latest information on
- TLS/SRP.
-
- Like any handshake function, this can be called on a closed
- TLS connection, or on a TLS connection that is already open.
- If called on an open connection it performs a re-handshake.
-
- If the function completes without raising an exception, the
- TLS connection will be open and available for data transfer.
-
- If an exception is raised, the connection will have been
- automatically closed (if it was ever open).
-
- @type username: str
- @param username: The SRP username.
-
- @type password: str
- @param password: The SRP password.
-
- @type session: L{tlslite.Session.Session}
- @param session: A TLS session to attempt to resume. This
- session must be an SRP session performed with the same username
- and password as were passed in. If the resumption does not
- succeed, a full SRP handshake will be performed.
-
- @type settings: L{tlslite.HandshakeSettings.HandshakeSettings}
- @param settings: Various settings which can be used to control
- the ciphersuites, certificate types, and SSL/TLS versions
- offered by the client.
-
- @type checker: L{tlslite.Checker.Checker}
- @param checker: A Checker instance. This instance will be
- invoked to examine the other party's authentication
- credentials, if the handshake completes succesfully.
-
- @type async: bool
- @param async: If False, this function will block until the
- handshake is completed. If True, this function will return a
- generator. Successive invocations of the generator will
- return 0 if it is waiting to read from the socket, 1 if it is
- waiting to write to the socket, or will raise StopIteration if
- the handshake operation is completed.
-
- @rtype: None or an iterable
- @return: If 'async' is True, a generator object will be
- returned.
-
- @raise socket.error: If a socket error occurs.
- @raise tlslite.errors.TLSAbruptCloseError: If the socket is closed
- without a preceding alert.
- @raise tlslite.errors.TLSAlert: If a TLS alert is signalled.
- @raise tlslite.errors.TLSAuthenticationError: If the checker
- doesn't like the other party's authentication credentials.
- """
- handshaker = self._handshakeClientAsync(srpParams = (username, password), session = session, settings = settings, checker = checker)
- if async:
- return handshaker
- for result in handshaker:
- pass
-
-
-
- def handshakeClientCert(self, certChain = None, privateKey = None, session = None, settings = None, checker = None, async = False):
- """Perform a certificate-based handshake in the role of client.
-
- This function performs an SSL or TLS handshake. The server
- will authenticate itself using an X.509 or cryptoID certificate
- chain. If the handshake succeeds, the server's certificate
- chain will be stored in the session's serverCertChain attribute.
- Unless a checker object is passed in, this function does no
- validation or checking of the server's certificate chain.
-
- If the server requests client authentication, the
- client will send the passed-in certificate chain, and use the
- passed-in private key to authenticate itself. If no
- certificate chain and private key were passed in, the client
- will attempt to proceed without client authentication. The
- server may or may not allow this.
-
- Like any handshake function, this can be called on a closed
- TLS connection, or on a TLS connection that is already open.
- If called on an open connection it performs a re-handshake.
-
- If the function completes without raising an exception, the
- TLS connection will be open and available for data transfer.
-
- If an exception is raised, the connection will have been
- automatically closed (if it was ever open).
-
- @type certChain: L{tlslite.X509CertChain.X509CertChain} or
- L{cryptoIDlib.CertChain.CertChain}
- @param certChain: The certificate chain to be used if the
- server requests client authentication.
-
- @type privateKey: L{tlslite.utils.RSAKey.RSAKey}
- @param privateKey: The private key to be used if the server
- requests client authentication.
-
- @type session: L{tlslite.Session.Session}
- @param session: A TLS session to attempt to resume. If the
- resumption does not succeed, a full handshake will be
- performed.
-
- @type settings: L{tlslite.HandshakeSettings.HandshakeSettings}
- @param settings: Various settings which can be used to control
- the ciphersuites, certificate types, and SSL/TLS versions
- offered by the client.
-
- @type checker: L{tlslite.Checker.Checker}
- @param checker: A Checker instance. This instance will be
- invoked to examine the other party's authentication
- credentials, if the handshake completes succesfully.
-
- @type async: bool
- @param async: If False, this function will block until the
- handshake is completed. If True, this function will return a
- generator. Successive invocations of the generator will
- return 0 if it is waiting to read from the socket, 1 if it is
- waiting to write to the socket, or will raise StopIteration if
- the handshake operation is completed.
-
- @rtype: None or an iterable
- @return: If 'async' is True, a generator object will be
- returned.
-
- @raise socket.error: If a socket error occurs.
- @raise tlslite.errors.TLSAbruptCloseError: If the socket is closed
- without a preceding alert.
- @raise tlslite.errors.TLSAlert: If a TLS alert is signalled.
- @raise tlslite.errors.TLSAuthenticationError: If the checker
- doesn't like the other party's authentication credentials.
- """
- handshaker = self._handshakeClientAsync(certParams = (certChain, privateKey), session = session, settings = settings, checker = checker)
- if async:
- return handshaker
- for result in handshaker:
- pass
-
-
-
- def handshakeClientUnknown(self, srpCallback = None, certCallback = None, session = None, settings = None, checker = None, async = False):
- """Perform a to-be-determined type of handshake in the role of client.
-
- This function performs an SSL or TLS handshake. If the server
- requests client certificate authentication, the
- certCallback will be invoked and should return a (certChain,
- privateKey) pair. If the callback returns None, the library
- will attempt to proceed without client authentication. The
- server may or may not allow this.
-
- If the server requests SRP authentication, the srpCallback
- will be invoked and should return a (username, password) pair.
- If the callback returns None, the local implementation will
- signal a user_canceled error alert.
-
- After the handshake completes, the client can inspect the
- connection's session attribute to determine what type of
- authentication was performed.
-
- Like any handshake function, this can be called on a closed
- TLS connection, or on a TLS connection that is already open.
- If called on an open connection it performs a re-handshake.
-
- If the function completes without raising an exception, the
- TLS connection will be open and available for data transfer.
-
- If an exception is raised, the connection will have been
- automatically closed (if it was ever open).
-
- @type srpCallback: callable
- @param srpCallback: The callback to be used if the server
- requests SRP authentication. If None, the client will not
- offer support for SRP ciphersuites.
-
- @type certCallback: callable
- @param certCallback: The callback to be used if the server
- requests client certificate authentication.
-
- @type session: L{tlslite.Session.Session}
- @param session: A TLS session to attempt to resume. If the
- resumption does not succeed, a full handshake will be
- performed.
-
- @type settings: L{tlslite.HandshakeSettings.HandshakeSettings}
- @param settings: Various settings which can be used to control
- the ciphersuites, certificate types, and SSL/TLS versions
- offered by the client.
-
- @type checker: L{tlslite.Checker.Checker}
- @param checker: A Checker instance. This instance will be
- invoked to examine the other party's authentication
- credentials, if the handshake completes succesfully.
-
- @type async: bool
- @param async: If False, this function will block until the
- handshake is completed. If True, this function will return a
- generator. Successive invocations of the generator will
- return 0 if it is waiting to read from the socket, 1 if it is
- waiting to write to the socket, or will raise StopIteration if
- the handshake operation is completed.
-
- @rtype: None or an iterable
- @return: If 'async' is True, a generator object will be
- returned.
-
- @raise socket.error: If a socket error occurs.
- @raise tlslite.errors.TLSAbruptCloseError: If the socket is closed
- without a preceding alert.
- @raise tlslite.errors.TLSAlert: If a TLS alert is signalled.
- @raise tlslite.errors.TLSAuthenticationError: If the checker
- doesn't like the other party's authentication credentials.
- """
- handshaker = self._handshakeClientAsync(unknownParams = (srpCallback, certCallback), session = session, settings = settings, checker = checker)
- if async:
- return handshaker
- for result in handshaker:
- pass
-
-
-
- def handshakeClientSharedKey(self, username, sharedKey, settings = None, checker = None, async = False):
- """Perform a shared-key handshake in the role of client.
-
- This function performs a shared-key handshake. Using shared
- symmetric keys of high entropy (128 bits or greater) mutually
- authenticates both parties to each other.
-
- TLS with shared-keys is non-standard. Most TLS
- implementations don't support it. See
- U{http://www.ietf.org/html.charters/tls-charter.html} for the
- latest information on TLS with shared-keys. If the shared-keys
- Internet-Draft changes or is superceded, TLS Lite will track
- those changes, so the shared-key support in later versions of
- TLS Lite may become incompatible with this version.
-
- Like any handshake function, this can be called on a closed
- TLS connection, or on a TLS connection that is already open.
- If called on an open connection it performs a re-handshake.
-
- If the function completes without raising an exception, the
- TLS connection will be open and available for data transfer.
-
- If an exception is raised, the connection will have been
- automatically closed (if it was ever open).
-
- @type username: str
- @param username: The shared-key username.
-
- @type sharedKey: str
- @param sharedKey: The shared key.
-
- @type settings: L{tlslite.HandshakeSettings.HandshakeSettings}
- @param settings: Various settings which can be used to control
- the ciphersuites, certificate types, and SSL/TLS versions
- offered by the client.
-
- @type checker: L{tlslite.Checker.Checker}
- @param checker: A Checker instance. This instance will be
- invoked to examine the other party's authentication
- credentials, if the handshake completes succesfully.
-
- @type async: bool
- @param async: If False, this function will block until the
- handshake is completed. If True, this function will return a
- generator. Successive invocations of the generator will
- return 0 if it is waiting to read from the socket, 1 if it is
- waiting to write to the socket, or will raise StopIteration if
- the handshake operation is completed.
-
- @rtype: None or an iterable
- @return: If 'async' is True, a generator object will be
- returned.
-
- @raise socket.error: If a socket error occurs.
- @raise tlslite.errors.TLSAbruptCloseError: If the socket is closed
- without a preceding alert.
- @raise tlslite.errors.TLSAlert: If a TLS alert is signalled.
- @raise tlslite.errors.TLSAuthenticationError: If the checker
- doesn't like the other party's authentication credentials.
- """
- handshaker = self._handshakeClientAsync(sharedKeyParams = (username, sharedKey), settings = settings, checker = checker)
- if async:
- return handshaker
- for result in handshaker:
- pass
-
-
-
- def _handshakeClientAsync(self, srpParams = (), certParams = (), unknownParams = (), sharedKeyParams = (), session = None, settings = None, checker = None, recursive = False):
- handshaker = self._handshakeClientAsyncHelper(srpParams = srpParams, certParams = certParams, unknownParams = unknownParams, sharedKeyParams = sharedKeyParams, session = session, settings = settings, recursive = recursive)
- for result in self._handshakeWrapperAsync(handshaker, checker):
- yield result
-
-
-
- def _handshakeClientAsyncHelper(self, srpParams, certParams, unknownParams, sharedKeyParams, session, settings, recursive):
- if not recursive:
- self._handshakeStart(client = True)
-
- srpUsername = None
- password = None
- clientCertChain = None
- privateKey = None
- srpCallback = None
- certCallback = None
- if srpParams:
- (srpUsername, password) = srpParams
- elif certParams:
- (clientCertChain, privateKey) = certParams
- elif unknownParams:
- (srpCallback, certCallback) = unknownParams
- elif sharedKeyParams:
- session = Session()._createSharedKey(*sharedKeyParams)
-
- if not settings:
- settings = HandshakeSettings()
-
- settings = settings._filter()
- if srpUsername and not password:
- raise ValueError('Caller passed a username but no password')
- not password
- if password and not srpUsername:
- raise ValueError('Caller passed a password but no username')
- not srpUsername
- if clientCertChain and not privateKey:
- raise ValueError('Caller passed a certChain but no privateKey')
- not privateKey
- if privateKey and not clientCertChain:
- raise ValueError('Caller passed a privateKey but no certChain')
- not clientCertChain
- if clientCertChain:
- foundType = False
-
- try:
- import cryptoIDlib.CertChain as cryptoIDlib
- if isinstance(clientCertChain, cryptoIDlib.CertChain.CertChain):
- if 'cryptoID' not in settings.certificateTypes:
- raise ValueError("Client certificate doesn't match Handshake Settings")
- 'cryptoID' not in settings.certificateTypes
- settings.certificateTypes = [
- 'cryptoID']
- foundType = True
- except ImportError:
- pass
-
- if not foundType and isinstance(clientCertChain, X509CertChain):
- if 'x509' not in settings.certificateTypes:
- raise ValueError("Client certificate doesn't match Handshake Settings")
- 'x509' not in settings.certificateTypes
- settings.certificateTypes = [
- 'x509']
- foundType = True
-
- if not foundType:
- raise ValueError('Unrecognized certificate type')
- foundType
-
- if session:
- if not session.valid():
- session = None
- elif session.resumable and session.srpUsername != srpUsername:
- raise ValueError("Session username doesn't match")
-
-
- if srpUsername and self.fault == Fault.badUsername:
- srpUsername += 'GARBAGE'
-
- if password and self.fault == Fault.badPassword:
- password += 'GARBAGE'
-
- if sharedKeyParams:
- identifier = sharedKeyParams[0]
- sharedKey = sharedKeyParams[1]
- if self.fault == Fault.badIdentifier:
- identifier += 'GARBAGE'
- session = Session()._createSharedKey(identifier, sharedKey)
- elif self.fault == Fault.badSharedKey:
- sharedKey += 'GARBAGE'
- session = Session()._createSharedKey(identifier, sharedKey)
-
-
- serverCertChain = None
- cipherSuite = 0
- certificateType = CertificateType.x509
- premasterSecret = None
- clientRandom = getRandomBytes(32)
- cipherSuites = []
- if srpParams:
- cipherSuites += CipherSuite.getSrpRsaSuites(settings.cipherNames)
- cipherSuites += CipherSuite.getSrpSuites(settings.cipherNames)
- elif certParams:
- cipherSuites += CipherSuite.getRsaSuites(settings.cipherNames)
- elif unknownParams:
- if srpCallback:
- cipherSuites += CipherSuite.getSrpRsaSuites(settings.cipherNames)
- cipherSuites += CipherSuite.getSrpSuites(settings.cipherNames)
-
- cipherSuites += CipherSuite.getRsaSuites(settings.cipherNames)
- elif sharedKeyParams:
- cipherSuites += CipherSuite.getRsaSuites(settings.cipherNames)
- else:
- cipherSuites += CipherSuite.getRsaSuites(settings.cipherNames)
- certificateTypes = settings._getCertificateTypes()
- self.version = settings.maxVersion
- if session:
- if not sharedKeyParams and session.cipherSuite not in cipherSuites:
- raise ValueError("Session's cipher suite not consistent with parameters")
- session.cipherSuite not in cipherSuites
- clientHello = ClientHello()
- clientHello.create(settings.maxVersion, clientRandom, session.sessionID, cipherSuites, certificateTypes, session.srpUsername)
- else:
- clientHello = ClientHello()
- clientHello.create(settings.maxVersion, clientRandom, createByteArraySequence([]), cipherSuites, certificateTypes, srpUsername)
- for result in self._sendMsg(clientHello):
- yield result
-
- for result in self._getMsg((ContentType.handshake, ContentType.alert), HandshakeType.server_hello):
- if result in (0, 1):
- yield result
- continue
-
- msg = result
- if isinstance(msg, ServerHello):
- serverHello = msg
- elif isinstance(msg, Alert):
- alert = msg
- if alert.description != AlertDescription.missing_srp_username:
- self._shutdown(False)
- raise TLSRemoteAlert(alert)
- alert.description != AlertDescription.missing_srp_username
- if not srpCallback:
- for result in self._sendError(AlertDescription.unexpected_message):
- yield result
-
-
- srpParams = srpCallback()
- if srpParams == None:
- for result in self._sendError(AlertDescription.user_canceled):
- yield result
-
-
- for result in self._handshakeClientAsyncHelper(srpParams, None, None, None, None, settings, True):
- yield result
-
- return None
- self.version = serverHello.server_version
- self._versionCheck = True
- if serverHello.server_version < settings.minVersion:
- for result in self._sendError(AlertDescription.protocol_version, 'Too old version: %s' % str(serverHello.server_version)):
- yield result
-
-
- if serverHello.server_version > settings.maxVersion:
- for result in self._sendError(AlertDescription.protocol_version, 'Too new version: %s' % str(serverHello.server_version)):
- yield result
-
-
- if serverHello.cipher_suite not in cipherSuites:
- for result in self._sendError(AlertDescription.illegal_parameter, 'Server responded with incorrect ciphersuite'):
- yield result
-
-
- if serverHello.certificate_type not in certificateTypes:
- for result in self._sendError(AlertDescription.illegal_parameter, 'Server responded with incorrect certificate type'):
- yield result
-
-
- if serverHello.compression_method != 0:
- for result in self._sendError(AlertDescription.illegal_parameter, 'Server responded with incorrect compression method'):
- yield result
-
-
- serverRandom = serverHello.random
- if session and session.sessionID and serverHello.session_id == session.sessionID:
- if sharedKeyParams:
- session.cipherSuite = serverHello.cipher_suite
- elif serverHello.cipher_suite != session.cipherSuite:
- for result in self._sendError(AlertDescription.illegal_parameter, "Server's ciphersuite doesn't match session"):
- yield result
-
-
- self.session = session
- self._calcPendingStates(clientRandom, serverRandom, settings.cipherImplementations)
- for result in self._getFinished():
- yield result
-
- for result in self._sendFinished():
- yield result
-
- self._handshakeDone(resumed = True)
- elif sharedKeyParams:
- for result in self._sendError(AlertDescription.user_canceled, 'Was expecting a shared-key resumption'):
- yield result
-
-
- cipherSuite = serverHello.cipher_suite
- certificateType = serverHello.certificate_type
- if cipherSuite in CipherSuite.srpSuites:
- for result in self._getMsg(ContentType.handshake, HandshakeType.server_key_exchange, cipherSuite):
- if result in (0, 1):
- yield result
- continue
-
- serverKeyExchange = result
- for result in self._getMsg(ContentType.handshake, HandshakeType.server_hello_done):
- if result in (0, 1):
- yield result
- continue
-
- serverHelloDone = result
- elif cipherSuite in CipherSuite.srpRsaSuites:
- for result in self._getMsg(ContentType.handshake, HandshakeType.certificate, certificateType):
- if result in (0, 1):
- yield result
- continue
-
- serverCertificate = result
- for result in self._getMsg(ContentType.handshake, HandshakeType.server_key_exchange, cipherSuite):
- if result in (0, 1):
- yield result
- continue
-
- serverKeyExchange = result
- for result in self._getMsg(ContentType.handshake, HandshakeType.server_hello_done):
- if result in (0, 1):
- yield result
- continue
-
- serverHelloDone = result
- elif cipherSuite in CipherSuite.rsaSuites:
- for result in self._getMsg(ContentType.handshake, HandshakeType.certificate, certificateType):
- if result in (0, 1):
- yield result
- continue
-
- serverCertificate = result
- for result in self._getMsg(ContentType.handshake, (HandshakeType.server_hello_done, HandshakeType.certificate_request)):
- if result in (0, 1):
- yield result
- continue
-
- msg = result
- certificateRequest = None
- if isinstance(msg, CertificateRequest):
- certificateRequest = msg
- for result in self._getMsg(ContentType.handshake, HandshakeType.server_hello_done):
- if result in (0, 1):
- yield result
- continue
-
- serverHelloDone = result
- elif isinstance(msg, ServerHelloDone):
- serverHelloDone = msg
-
- else:
- raise AssertionError()
- if cipherSuite in CipherSuite.srpSuites in CipherSuite.srpSuites + CipherSuite.srpRsaSuites:
- N = serverKeyExchange.srp_N
- g = serverKeyExchange.srp_g
- s = serverKeyExchange.srp_s
- B = serverKeyExchange.srp_B
- if (g, N) not in goodGroupParameters:
- for result in self._sendError(AlertDescription.untrusted_srp_parameters, 'Unknown group parameters'):
- yield result
-
-
- if numBits(N) < settings.minKeySize:
- for result in self._sendError(AlertDescription.untrusted_srp_parameters, 'N value is too small: %d' % numBits(N)):
- yield result
-
-
- if numBits(N) > settings.maxKeySize:
- for result in self._sendError(AlertDescription.untrusted_srp_parameters, 'N value is too large: %d' % numBits(N)):
- yield result
-
-
- if B % N == 0:
- for result in self._sendError(AlertDescription.illegal_parameter, 'Suspicious B value'):
- yield result
-
-
- if cipherSuite in CipherSuite.srpRsaSuites:
- hashBytes = serverKeyExchange.hash(clientRandom, serverRandom)
- sigBytes = serverKeyExchange.signature
- if len(sigBytes) == 0:
- for result in self._sendError(AlertDescription.illegal_parameter, 'Server sent an SRP ServerKeyExchange message without a signature'):
- yield result
-
-
- for result in self._getKeyFromChain(serverCertificate, settings):
- if result in (0, 1):
- yield result
- continue
-
- (publicKey, serverCertChain) = result
- if not publicKey.verify(sigBytes, hashBytes):
- for result in self._sendError(AlertDescription.decrypt_error, 'Signature failed to verify'):
- yield result
-
-
-
- a = bytesToNumber(getRandomBytes(32))
- A = powMod(g, a, N)
- x = makeX(bytesToString(s), srpUsername, password)
- v = powMod(g, x, N)
- u = makeU(N, A, B)
- k = makeK(N, g)
- S = powMod((B - k * v) % N, a + u * x, N)
- if self.fault == Fault.badA:
- A = N
- S = 0
-
- premasterSecret = numberToBytes(S)
- for result in self._sendMsg(ClientKeyExchange(cipherSuite).createSRP(A)):
- yield result
-
- elif cipherSuite in CipherSuite.rsaSuites:
- if certificateRequest:
- if unknownParams and certCallback:
- certParamsNew = certCallback()
- if certParamsNew:
- (clientCertChain, privateKey) = certParamsNew
-
-
-
- for result in self._getKeyFromChain(serverCertificate, settings):
- if result in (0, 1):
- yield result
- continue
-
- (publicKey, serverCertChain) = result
- premasterSecret = getRandomBytes(48)
- premasterSecret[0] = settings.maxVersion[0]
- premasterSecret[1] = settings.maxVersion[1]
- if self.fault == Fault.badPremasterPadding:
- premasterSecret[0] = 5
-
- if self.fault == Fault.shortPremasterSecret:
- premasterSecret = premasterSecret[:-1]
-
- encryptedPreMasterSecret = publicKey.encrypt(premasterSecret)
- if certificateRequest:
- clientCertificate = Certificate(certificateType)
- if clientCertChain:
- wrongType = False
- if certificateType == CertificateType.x509:
- if not isinstance(clientCertChain, X509CertChain):
- wrongType = True
-
- elif certificateType == CertificateType.cryptoID:
- if not isinstance(clientCertChain, cryptoIDlib.CertChain.CertChain):
- wrongType = True
-
-
- if wrongType:
- for result in self._sendError(AlertDescription.handshake_failure, 'Client certificate is of wrong type'):
- yield result
-
-
- clientCertificate.create(clientCertChain)
-
- for result in self._sendMsg(clientCertificate):
- yield result
-
- else:
- privateKey = None
- clientCertChain = None
- clientKeyExchange = ClientKeyExchange(cipherSuite, self.version)
- clientKeyExchange.createRSA(encryptedPreMasterSecret)
- for result in self._sendMsg(clientKeyExchange):
- yield result
-
- if certificateRequest and privateKey:
- if self.version == (3, 0):
- session = Session()
- session._calcMasterSecret(self.version, premasterSecret, clientRandom, serverRandom)
- verifyBytes = self._calcSSLHandshakeHash(session.masterSecret, '')
- elif self.version in ((3, 1), (3, 2)):
- verifyBytes = stringToBytes(self._handshake_md5.digest() + self._handshake_sha.digest())
-
- if self.fault == Fault.badVerifyMessage:
- verifyBytes[0] = (verifyBytes[0] + 1) % 256
-
- signedBytes = privateKey.sign(verifyBytes)
- certificateVerify = CertificateVerify()
- certificateVerify.create(signedBytes)
- for result in self._sendMsg(certificateVerify):
- yield result
-
-
-
- self.session = Session()
- self.session._calcMasterSecret(self.version, premasterSecret, clientRandom, serverRandom)
- self.session.sessionID = serverHello.session_id
- self.session.cipherSuite = cipherSuite
- self.session.srpUsername = srpUsername
- self.session.clientCertChain = clientCertChain
- self.session.serverCertChain = serverCertChain
- self._calcPendingStates(clientRandom, serverRandom, settings.cipherImplementations)
- for result in self._sendFinished():
- yield result
-
- for result in self._getFinished():
- yield result
-
- self.session._setResumable(True)
- self._handshakeDone(resumed = False)
-
-
- def handshakeServer(self, sharedKeyDB = None, verifierDB = None, certChain = None, privateKey = None, reqCert = False, sessionCache = None, settings = None, checker = None):
- """Perform a handshake in the role of server.
-
- This function performs an SSL or TLS handshake. Depending on
- the arguments and the behavior of the client, this function can
- perform a shared-key, SRP, or certificate-based handshake. It
- can also perform a combined SRP and server-certificate
- handshake.
-
- Like any handshake function, this can be called on a closed
- TLS connection, or on a TLS connection that is already open.
- If called on an open connection it performs a re-handshake.
- This function does not send a Hello Request message before
- performing the handshake, so if re-handshaking is required,
- the server must signal the client to begin the re-handshake
- through some other means.
-
- If the function completes without raising an exception, the
- TLS connection will be open and available for data transfer.
-
- If an exception is raised, the connection will have been
- automatically closed (if it was ever open).
-
- @type sharedKeyDB: L{tlslite.SharedKeyDB.SharedKeyDB}
- @param sharedKeyDB: A database of shared symmetric keys
- associated with usernames. If the client performs a
- shared-key handshake, the session's sharedKeyUsername
- attribute will be set.
-
- @type verifierDB: L{tlslite.VerifierDB.VerifierDB}
- @param verifierDB: A database of SRP password verifiers
- associated with usernames. If the client performs an SRP
- handshake, the session's srpUsername attribute will be set.
-
- @type certChain: L{tlslite.X509CertChain.X509CertChain} or
- L{cryptoIDlib.CertChain.CertChain}
- @param certChain: The certificate chain to be used if the
- client requests server certificate authentication.
-
- @type privateKey: L{tlslite.utils.RSAKey.RSAKey}
- @param privateKey: The private key to be used if the client
- requests server certificate authentication.
-
- @type reqCert: bool
- @param reqCert: Whether to request client certificate
- authentication. This only applies if the client chooses server
- certificate authentication; if the client chooses SRP or
- shared-key authentication, this will be ignored. If the client
- performs a client certificate authentication, the sessions's
- clientCertChain attribute will be set.
-
- @type sessionCache: L{tlslite.SessionCache.SessionCache}
- @param sessionCache: An in-memory cache of resumable sessions.
- The client can resume sessions from this cache. Alternatively,
- if the client performs a full handshake, a new session will be
- added to the cache.
-
- @type settings: L{tlslite.HandshakeSettings.HandshakeSettings}
- @param settings: Various settings which can be used to control
- the ciphersuites and SSL/TLS version chosen by the server.
-
- @type checker: L{tlslite.Checker.Checker}
- @param checker: A Checker instance. This instance will be
- invoked to examine the other party's authentication
- credentials, if the handshake completes succesfully.
-
- @raise socket.error: If a socket error occurs.
- @raise tlslite.errors.TLSAbruptCloseError: If the socket is closed
- without a preceding alert.
- @raise tlslite.errors.TLSAlert: If a TLS alert is signalled.
- @raise tlslite.errors.TLSAuthenticationError: If the checker
- doesn't like the other party's authentication credentials.
- """
- for result in self.handshakeServerAsync(sharedKeyDB, verifierDB, certChain, privateKey, reqCert, sessionCache, settings, checker):
- pass
-
-
-
- def handshakeServerAsync(self, sharedKeyDB = None, verifierDB = None, certChain = None, privateKey = None, reqCert = False, sessionCache = None, settings = None, checker = None):
- '''Start a server handshake operation on the TLS connection.
-
- This function returns a generator which behaves similarly to
- handshakeServer(). Successive invocations of the generator
- will return 0 if it is waiting to read from the socket, 1 if it is
- waiting to write to the socket, or it will raise StopIteration
- if the handshake operation is complete.
-
- @rtype: iterable
- @return: A generator; see above for details.
- '''
- handshaker = self._handshakeServerAsyncHelper(sharedKeyDB = sharedKeyDB, verifierDB = verifierDB, certChain = certChain, privateKey = privateKey, reqCert = reqCert, sessionCache = sessionCache, settings = settings)
- for result in self._handshakeWrapperAsync(handshaker, checker):
- yield result
-
-
-
- def _handshakeServerAsyncHelper(self, sharedKeyDB, verifierDB, certChain, privateKey, reqCert, sessionCache, settings):
- self._handshakeStart(client = False)
- if not sharedKeyDB and not verifierDB and not certChain:
- raise ValueError('Caller passed no authentication credentials')
- not certChain
- if certChain and not privateKey:
- raise ValueError('Caller passed a certChain but no privateKey')
- not privateKey
- if privateKey and not certChain:
- raise ValueError('Caller passed a privateKey but no certChain')
- not certChain
- if not settings:
- settings = HandshakeSettings()
-
- settings = settings._filter()
- cipherSuites = []
- if verifierDB:
- if certChain:
- cipherSuites += CipherSuite.getSrpRsaSuites(settings.cipherNames)
-
- cipherSuites += CipherSuite.getSrpSuites(settings.cipherNames)
-
- if sharedKeyDB or certChain:
- cipherSuites += CipherSuite.getRsaSuites(settings.cipherNames)
-
- certificateType = None
- if certChain:
-
- try:
- import cryptoIDlib.CertChain as cryptoIDlib
- if isinstance(certChain, cryptoIDlib.CertChain.CertChain):
- certificateType = CertificateType.cryptoID
- except ImportError:
- pass
-
- if isinstance(certChain, X509CertChain):
- certificateType = CertificateType.x509
-
- if certificateType == None:
- raise ValueError('Unrecognized certificate type')
- certificateType == None
-
- clientCertChain = None
- serverCertChain = None
- postFinishedError = None
- self.version = settings.maxVersion
- for result in self._getMsg(ContentType.handshake, HandshakeType.client_hello):
- if result in (0, 1):
- yield result
- continue
-
- clientHello = result
- if clientHello.client_version < settings.minVersion:
- self.version = settings.minVersion
- for result in self._sendError(AlertDescription.protocol_version, 'Too old version: %s' % str(clientHello.client_version)):
- yield result
-
- elif clientHello.client_version > settings.maxVersion:
- self.version = settings.maxVersion
- else:
- self.version = clientHello.client_version
- clientRandom = clientHello.random
- serverRandom = getRandomBytes(32)
- for cipherSuite in cipherSuites:
- if cipherSuite in clientHello.cipher_suites:
- break
- continue
- else:
- for result in self._sendError(AlertDescription.handshake_failure):
- yield result
-
- if clientHello.session_id:
- if sharedKeyDB or sessionCache:
- session = None
- if sharedKeyDB and len(clientHello.session_id) == 16:
-
- try:
- for x in range(16):
- if clientHello.session_id[x] == 0:
- break
- continue
-
- self.allegedSharedKeyUsername = bytesToString(clientHello.session_id[:x])
- session = sharedKeyDB[self.allegedSharedKeyUsername]
- if not session.sharedKey:
- raise AssertionError()
- session.sharedKey
- session.cipherSuite = cipherSuite
- except KeyError:
- pass
- except:
- None<EXCEPTION MATCH>KeyError
-
-
- None<EXCEPTION MATCH>KeyError
- if sessionCache and not session:
-
- try:
- session = sessionCache[bytesToString(clientHello.session_id)]
- if session.sharedKey:
- raise AssertionError()
- session.sharedKey
- if not session.resumable:
- raise AssertionError()
- session.resumable
- if session.cipherSuite not in cipherSuites:
- for result in self._sendError(AlertDescription.handshake_failure):
- yield result
-
-
- if session.cipherSuite not in clientHello.cipher_suites:
- for result in self._sendError(AlertDescription.handshake_failure):
- yield result
-
-
- if clientHello.srp_username:
- if clientHello.srp_username != session.srpUsername:
- for result in self._sendError(AlertDescription.handshake_failure):
- yield result
-
-
- except KeyError:
- pass
- except:
- None<EXCEPTION MATCH>KeyError
-
-
- None<EXCEPTION MATCH>KeyError
- if session:
- self.session = session
- serverHello = ServerHello()
- serverHello.create(self.version, serverRandom, session.sessionID, session.cipherSuite, certificateType)
- for result in self._sendMsg(serverHello):
- yield result
-
- self._versionCheck = True
- self._calcPendingStates(clientRandom, serverRandom, settings.cipherImplementations)
- for result in self._sendFinished():
- yield result
-
- for result in self._getFinished():
- yield result
-
- self._handshakeDone(resumed = True)
- return None
-
- if cipherSuite in CipherSuite.rsaSuites and not certChain:
- for result in self._sendError(AlertDescription.handshake_failure):
- yield result
-
-
- if cipherSuite in CipherSuite.rsaSuites + CipherSuite.srpRsaSuites:
- if certificateType not in clientHello.certificate_types:
- for result in self._sendError(AlertDescription.handshake_failure, "the client doesn't support my certificate type"):
- yield result
-
-
- serverCertChain = certChain
-
- if sessionCache:
- sessionID = getRandomBytes(32)
- else:
- sessionID = createByteArraySequence([])
- if cipherSuite in CipherSuite.srpSuites + CipherSuite.srpRsaSuites:
- if not clientHello.srp_username:
- for result in self._sendMsg(Alert().create(AlertDescription.missing_srp_username, AlertLevel.warning)):
- yield result
-
- for result in self._getMsg(ContentType.handshake, HandshakeType.client_hello):
- if result in (0, 1):
- yield result
- continue
-
- clientHello = result
- if clientHello.client_version < settings.minVersion:
- self.version = settings.minVersion
- for result in self._sendError(AlertDescription.protocol_version, 'Too old version: %s' % str(clientHello.client_version)):
- yield result
-
- elif clientHello.client_version > settings.maxVersion:
- self.version = settings.maxVersion
- else:
- self.version = clientHello.client_version
- cipherSuites = _[1]
- for cipherSuite in cipherSuites:
- if cipherSuite in clientHello.cipher_suites:
- break
- continue
- []
- else:
- for result in self._sendError(AlertDescription.handshake_failure):
- yield result
- []
-
- clientRandom = clientHello.random
- serverRandom = getRandomBytes(32)
- if not clientHello.srp_username:
- for result in self._sendError(AlertDescription.illegal_parameter, 'Client resent a hello, but without the SRP username'):
- yield result
-
-
-
- self.allegedSrpUsername = clientHello.srp_username
-
- try:
- entry = verifierDB[self.allegedSrpUsername]
- except KeyError:
- for result in self._sendError(AlertDescription.unknown_srp_username):
- yield result
-
-
- (N, g, s, v) = entry
- b = bytesToNumber(getRandomBytes(32))
- k = makeK(N, g)
- B = (powMod(g, b, N) + k * v) % N
- serverKeyExchange = ServerKeyExchange(cipherSuite)
- serverKeyExchange.createSRP(N, g, stringToBytes(s), B)
- if cipherSuite in CipherSuite.srpRsaSuites:
- hashBytes = serverKeyExchange.hash(clientRandom, serverRandom)
- serverKeyExchange.signature = privateKey.sign(hashBytes)
-
- msgs = []
- serverHello = ServerHello()
- serverHello.create(self.version, serverRandom, sessionID, cipherSuite, certificateType)
- msgs.append(serverHello)
- if cipherSuite in CipherSuite.srpRsaSuites:
- certificateMsg = Certificate(certificateType)
- certificateMsg.create(serverCertChain)
- msgs.append(certificateMsg)
-
- msgs.append(serverKeyExchange)
- msgs.append(ServerHelloDone())
- for result in self._sendMsgs(msgs):
- yield result
-
- self._versionCheck = True
- for result in self._getMsg(ContentType.handshake, HandshakeType.client_key_exchange, cipherSuite):
- if result in (0, 1):
- yield result
- continue
-
- clientKeyExchange = result
- A = clientKeyExchange.srp_A
- if A % N == 0:
- postFinishedError = (AlertDescription.illegal_parameter, 'Suspicious A value')
-
- u = makeU(N, A, B)
- S = powMod(A * powMod(v, u, N) % N, b, N)
- premasterSecret = numberToBytes(S)
- elif cipherSuite in CipherSuite.rsaSuites:
- msgs = []
- msgs.append(ServerHello().create(self.version, serverRandom, sessionID, cipherSuite, certificateType))
- msgs.append(Certificate(certificateType).create(serverCertChain))
- if reqCert:
- msgs.append(CertificateRequest())
-
- msgs.append(ServerHelloDone())
- for result in self._sendMsgs(msgs):
- yield result
-
- self._versionCheck = True
- if reqCert:
- if self.version == (3, 0):
- for result in self._getMsg((ContentType.handshake, ContentType.alert), HandshakeType.certificate, certificateType):
- if result in (0, 1):
- yield result
- continue
-
- msg = result
- if isinstance(msg, Alert):
- alert = msg
- if alert.description != AlertDescription.no_certificate:
- self._shutdown(False)
- raise TLSRemoteAlert(alert)
- alert.description != AlertDescription.no_certificate
- elif isinstance(msg, Certificate):
- clientCertificate = msg
- if clientCertificate.certChain and clientCertificate.certChain.getNumCerts() != 0:
- clientCertChain = clientCertificate.certChain
-
- else:
- raise AssertionError()
- isinstance(msg, Alert)
- if self.version in ((3, 1), (3, 2)):
- for result in self._getMsg(ContentType.handshake, HandshakeType.certificate, certificateType):
- if result in (0, 1):
- yield result
- continue
-
- clientCertificate = result
- if clientCertificate.certChain and clientCertificate.certChain.getNumCerts() != 0:
- clientCertChain = clientCertificate.certChain
-
- else:
- raise AssertionError()
- self.version in ((3, 1), (3, 2))
- for result in self._getMsg(ContentType.handshake, HandshakeType.client_key_exchange, cipherSuite):
- if result in (0, 1):
- yield result
- continue
-
- clientKeyExchange = result
- premasterSecret = privateKey.decrypt(clientKeyExchange.encryptedPreMasterSecret)
- randomPreMasterSecret = getRandomBytes(48)
- versionCheck = (premasterSecret[0], premasterSecret[1])
- if not premasterSecret:
- premasterSecret = randomPreMasterSecret
- elif len(premasterSecret) != 48:
- premasterSecret = randomPreMasterSecret
- elif versionCheck != clientHello.client_version:
- if versionCheck != self.version:
- premasterSecret = randomPreMasterSecret
-
-
- if clientCertChain:
- if self.version == (3, 0):
- session = Session()
- session._calcMasterSecret(self.version, premasterSecret, clientRandom, serverRandom)
- verifyBytes = self._calcSSLHandshakeHash(session.masterSecret, '')
- elif self.version in ((3, 1), (3, 2)):
- verifyBytes = stringToBytes(self._handshake_md5.digest() + self._handshake_sha.digest())
-
- for result in self._getMsg(ContentType.handshake, HandshakeType.certificate_verify):
- if result in (0, 1):
- yield result
- continue
-
- certificateVerify = result
- publicKey = clientCertChain.getEndEntityPublicKey()
- if len(publicKey) < settings.minKeySize:
- postFinishedError = (AlertDescription.handshake_failure, "Client's public key too small: %d" % len(publicKey))
-
- if len(publicKey) > settings.maxKeySize:
- postFinishedError = (AlertDescription.handshake_failure, "Client's public key too large: %d" % len(publicKey))
-
- if not publicKey.verify(certificateVerify.signature, verifyBytes):
- postFinishedError = (AlertDescription.decrypt_error, 'Signature failed to verify')
-
-
-
- self.session = Session()
- self.session._calcMasterSecret(self.version, premasterSecret, clientRandom, serverRandom)
- self.session.sessionID = sessionID
- self.session.cipherSuite = cipherSuite
- self.session.srpUsername = self.allegedSrpUsername
- self.session.clientCertChain = clientCertChain
- self.session.serverCertChain = serverCertChain
- self._calcPendingStates(clientRandom, serverRandom, settings.cipherImplementations)
- for result in self._getFinished():
- yield result
-
- if postFinishedError:
- for result in self._sendError(*postFinishedError):
- yield result
-
-
- for result in self._sendFinished():
- yield result
-
- if sessionCache and sessionID:
- sessionCache[bytesToString(sessionID)] = self.session
-
- self.session._setResumable(True)
- self._handshakeDone(resumed = False)
-
-
- def _handshakeWrapperAsync(self, handshaker, checker):
- if not self.fault:
-
- try:
- for result in handshaker:
- yield result
-
- if checker:
-
- try:
- checker(self)
- except TLSAuthenticationError:
- alert = Alert().create(AlertDescription.close_notify, AlertLevel.fatal)
- for result in self._sendMsg(alert):
- yield result
-
- raise
- except:
- None<EXCEPTION MATCH>TLSAuthenticationError
-
-
- None<EXCEPTION MATCH>TLSAuthenticationError
- self._shutdown(False)
- raise
-
- else:
-
- try:
- for result in handshaker:
- yield result
-
- if checker:
-
- try:
- checker(self)
- except TLSAuthenticationError:
- alert = Alert().create(AlertDescription.close_notify, AlertLevel.fatal)
- for result in self._sendMsg(alert):
- yield result
-
- raise
- except:
- None<EXCEPTION MATCH>TLSAuthenticationError
-
-
- None<EXCEPTION MATCH>TLSAuthenticationError
- except socket.error:
- e = None
- raise TLSFaultError('socket error!')
- except TLSAbruptCloseError:
- e = None
- raise TLSFaultError('abrupt close error!')
- except TLSAlert:
- alert = None
- if alert.description not in Fault.faultAlerts[self.fault]:
- raise TLSFaultError(str(alert))
- alert.description not in Fault.faultAlerts[self.fault]
- except:
- self._shutdown(False)
- raise
-
- raise TLSFaultError('No error!')
- return self.fault
-
-
- def _getKeyFromChain(self, certificate, settings):
- certChain = certificate.certChain
- if not certChain or certChain.getNumCerts() == 0:
- for result in self._sendError(AlertDescription.illegal_parameter, 'Other party sent a Certificate message without certificates'):
- yield result
-
-
- publicKey = certChain.getEndEntityPublicKey()
- if len(publicKey) < settings.minKeySize:
- for result in self._sendError(AlertDescription.handshake_failure, "Other party's public key too small: %d" % len(publicKey)):
- yield result
-
-
- if len(publicKey) > settings.maxKeySize:
- for result in self._sendError(AlertDescription.handshake_failure, "Other party's public key too large: %d" % len(publicKey)):
- yield result
-
-
- yield (publicKey, certChain)
-
-
-